package com.dawn.module.hospital.controller.admin.statics;

import cn.hutool.core.date.LocalDateTimeUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.dawn.framework.common.pojo.CommonResult;
import com.dawn.framework.common.pojo.PageResult;
import com.dawn.module.hospital.config.CDBPayConfig;
import com.dawn.module.hospital.controller.admin.statics.vo.*;
import com.dawn.module.hospital.enums.ErrorCodeConstants;
import com.dawn.module.hospital.service.StaticsService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;


/**
 * @description:
 * @author: cnsu-cmh
 * @time: 2024/8/19 13:17
 */
@Tag(name = "统计相关 管理后台 - bh")
@RestController
@RequestMapping("/bh/statics")
@Validated
public class StaticsController {

    @Autowired
    private StaticsService staticsService;

    @Autowired
    private CDBPayConfig payConfig;

    @Operation(summary = "首页")
    @GetMapping("/index")
    public CommonResult index(){
        Map resultMap = new HashMap<>();
        HashMap amountMap = staticsService.payAmountWeek();
        resultMap.putAll(amountMap);
        HashMap countMap = staticsService.numCount();
        resultMap.putAll(countMap);
        return CommonResult.success(resultMap);
    }

    @Operation(summary = "payCount")
    @GetMapping("/payCount")
    public CommonResult payCount(@Valid TradeOrderTrendReqVO reqVO){
        CommonResult result = staticsService.payCount(reqVO);
        return result;
    }

    @Operation(summary = "payTypeCount")
    @GetMapping("/payTypeCount")
    public CommonResult payTypeCount(@Valid TradeOrderTrendReqVO reqVO){
        CommonResult result = staticsService.payTypeCount(reqVO);
        return result;
    }

    @Operation(summary = "获得每天创建档案数量")
    @GetMapping("/patient/count")
    public CommonResult patientCount(@Valid TradeOrderTrendReqVO reqVO){
        CommonResult commonResult = staticsService.patientCount(reqVO);
        return commonResult;
    }

    @Operation(summary = "获得业务数量")
    @GetMapping("/biz/count")
    public CommonResult bizCount(@Valid TradeOrderTrendReqVO reqVO){
        Map map = new HashMap<>();
        map.put("register",staticsService.registerCount(reqVO).getData());
        map.put("bill",staticsService.billCount(reqVO).getData());
        map.put("inHospital",staticsService.inHospitalCount(reqVO).getData());
        return CommonResult.success(map);
    }

    @Operation(summary = "病人档案")
    @GetMapping("/patient/list")
    @PreAuthorize("@ss.hasPermission('bh:patient:query')")
    public CommonResult<PageResult<PatientRespVO>> patientList(@Valid SearchReqVO pageReqVO){

        if (pageReqVO.getSearchTime() != null && pageReqVO.getSearchTime().length > 1) {
            LocalDateTime beginDateTime = pageReqVO.getSearchTime()[0];
            LocalDateTime endDateTime = pageReqVO.getSearchTime()[1];
            pageReqVO.setBeginDate(LocalDateTimeUtil.formatNormal(beginDateTime));
            pageReqVO.setEndDate(LocalDateTimeUtil.formatNormal(endDateTime));
        }

        PageResult<PatientRespVO> pageResult = staticsService.getPatientPage(pageReqVO);

        return CommonResult.success(pageResult);
    }


    @Operation(summary = "挂号记录")
    @GetMapping("/register/list")
    @PreAuthorize("@ss.hasPermission('bh:register:query')")
    public CommonResult<PageResult<RegisterRespVO>> pageRegister(@Valid SearchReqVO pageReqVO){

        if (pageReqVO.getSearchTime() != null && pageReqVO.getSearchTime().length > 1) {
            LocalDateTime beginDateTime = pageReqVO.getSearchTime()[0];
            LocalDateTime endDateTime = pageReqVO.getSearchTime()[1];
            pageReqVO.setBeginDate(LocalDateTimeUtil.formatNormal(beginDateTime));
            pageReqVO.setEndDate(LocalDateTimeUtil.formatNormal(endDateTime));
        }

        PageResult<RegisterRespVO> pageResult = staticsService.getRegisterPage(pageReqVO);

        return CommonResult.success(pageResult);
    }

    @Operation(summary = "门诊缴费账单")
    @GetMapping("/outpatient/bill")
    @PreAuthorize("@ss.hasPermission('bh:outpatient:query')")
    public CommonResult<PageResult<BillRespVO>> pageBill(@Valid SearchReqVO pageReqVO){

        if (pageReqVO.getSearchTime() != null && pageReqVO.getSearchTime().length > 1) {
            LocalDateTime beginDateTime = pageReqVO.getSearchTime()[0];
            LocalDateTime endDateTime = pageReqVO.getSearchTime()[1];
            pageReqVO.setBeginDate(LocalDateTimeUtil.formatNormal(beginDateTime));
            pageReqVO.setEndDate(LocalDateTimeUtil.formatNormal(endDateTime));
        }

        PageResult<BillRespVO> pageResult = staticsService.getBillPage(pageReqVO);

        return CommonResult.success(pageResult);
    }

    @Operation(summary = "门诊缴费记录")
    @GetMapping("/outpatient/list")
    @PreAuthorize("@ss.hasPermission('bh:outpatient:query')")
    public CommonResult<PageResult<OutpatientRespVO>> pageOutpatient(@Valid SearchReqVO pageReqVO){

        if (pageReqVO.getSearchTime() != null && pageReqVO.getSearchTime().length > 1) {
            LocalDateTime beginDateTime = pageReqVO.getSearchTime()[0];
            LocalDateTime endDateTime = pageReqVO.getSearchTime()[1];
            pageReqVO.setBeginDate(LocalDateTimeUtil.formatNormal(beginDateTime));
            pageReqVO.setEndDate(LocalDateTimeUtil.formatNormal(endDateTime));
        }

        PageResult<OutpatientRespVO> pageResult = staticsService.getOutpatientPage(pageReqVO);

        return CommonResult.success(pageResult);
    }

    @Operation(summary = "费用明细")
    @GetMapping("/outpatient/price")
    @PreAuthorize("@ss.hasPermission('bh:outpatient:query')")
    public CommonResult getPrice( SearchReqVO pageReqVO){
        return staticsService.getPriceList(pageReqVO.getOrderNo());
    }


    @Operation(summary = "处方签二维码")
    @GetMapping("/outpatient/qr")
    @PreAuthorize("@ss.hasPermission('bh:outpatient:query')")
    public CommonResult<PageResult<OutpatientQrResp>> pageOutpatientQr(@Valid SearchReqVO pageReqVO){
        if (pageReqVO.getSearchTime() != null && pageReqVO.getSearchTime().length > 1) {
            LocalDateTime beginDateTime = pageReqVO.getSearchTime()[0];
            LocalDateTime endDateTime = pageReqVO.getSearchTime()[1];
            pageReqVO.setBeginDate(LocalDateTimeUtil.formatNormal(beginDateTime));
            pageReqVO.setEndDate(LocalDateTimeUtil.formatNormal(endDateTime));
        }

        PageResult<OutpatientQrResp> pageResult = staticsService.getOutpatientQrPage(pageReqVO);

        return CommonResult.success(pageResult);
    }

    @Operation(summary = "住院预交记录")
    @GetMapping("/inhospital/list")
    @PreAuthorize("@ss.hasPermission('bh:inhospital:query')")
    public CommonResult<PageResult<InhospitalRespVO>> pageInhospital(@Valid SearchReqVO pageReqVO){

        if (pageReqVO.getSearchTime() != null && pageReqVO.getSearchTime().length > 1) {
            LocalDateTime beginDateTime = pageReqVO.getSearchTime()[0];
            LocalDateTime endDateTime = pageReqVO.getSearchTime()[1];
            pageReqVO.setBeginDate(LocalDateTimeUtil.formatNormal(beginDateTime));
            pageReqVO.setEndDate(LocalDateTimeUtil.formatNormal(endDateTime));
        }

        PageResult<InhospitalRespVO> pageResult = staticsService.getInhospitalPage(pageReqVO);

        return CommonResult.success(pageResult);
    }



    @Operation(summary = "对账单")
    @GetMapping("/bill")
    @PreAuthorize("@ss.hasPermission('bh:bill:query')")
    public CommonResult billQuery(@Valid BillReqVO billReqVO){

        String mchType = billReqVO.getMchType();
        String mchNo = payConfig.getMchNo(mchType);
        if (StringUtils.isEmpty(mchNo)) {
            return CommonResult.error(ErrorCodeConstants.PAY_CONFIG_MCHNO_NOT_EXISTS);
        }

        billReqVO.setMchNo(mchNo);
        JSONObject jsonObject = staticsService.billQuery(billReqVO);
        List<JSONObject> resultList = new LinkedList<>();
        if (!CollectionUtils.isEmpty(jsonObject)) {
            BigDecimal p_fee = new BigDecimal(0);
            if(!StringUtils.isEmpty(jsonObject.getJSONArray("payOrderList"))) {
                JSONArray payOrderList = jsonObject.getJSONArray("payOrderList");
                List<JSONObject> newList = new LinkedList<>();
                for (Object payOrderObj : payOrderList) {
                    JSONObject payOrder = (JSONObject)payOrderObj;
                    BigDecimal total_fee = payOrder.getBigDecimal("payAmount");
                    String trade_item = payOrder.getString("content");
                    if(!StringUtils.isEmpty(trade_item)) {
                        try{
                            JSONObject m = JSON.parseObject(trade_item);
                            if(!CollectionUtils.isEmpty(m)) {
                                payOrder.putAll(m);
                            }
                        }catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                    newList.add(payOrder);
                    p_fee = p_fee.add(total_fee);
                }

                if(!CollectionUtils.isEmpty(newList)) {
                    resultList.addAll(newList);
                }

                JSONObject total = new JSONObject();
                total.put("title","合计收款");
                total.put("channelNo", newList.size() + "笔");
                total.put("payAmount", p_fee.toString());
                resultList.add(total);
            }

            BigDecimal r_fee = new BigDecimal(0);
            if(!StringUtils.isEmpty(jsonObject.getJSONArray("refundOrderList"))) {
                JSONArray refundOrderList = jsonObject.getJSONArray("refundOrderList");
                List<JSONObject> newList = new LinkedList<>();
                for (Object refundOrderObj : refundOrderList) {
                    JSONObject refundOrder = (JSONObject)refundOrderObj;
                    BigDecimal total_fee = refundOrder.getBigDecimal("refundAmount");
                    String trade_item = refundOrder.getString("content");
                    if(!StringUtils.isEmpty(trade_item)) {
                        try{
                            JSONObject m = JSON.parseObject(trade_item);
                            if(!CollectionUtils.isEmpty(m)) {
                                refundOrder.putAll(m);
                            }
                        }catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                    newList.add(refundOrder);
                    r_fee = r_fee.add(total_fee);
                }

                if(!CollectionUtils.isEmpty(newList)) {
                    resultList.addAll(newList);
                }

                JSONObject total = new JSONObject();
                total.put("title","合计退款");
                total.put("channelNo",newList.size() + "笔");
                total.put("refundAmount","-" + r_fee.toString());
                resultList.add(total);

            }
            BigDecimal total_fee = p_fee.subtract(r_fee);
            JSONObject total = new JSONObject();
            total.put("title","总计收入");
            total.put("payAmount",total_fee.toString());
            resultList.add(total);
        }
        return CommonResult.success(resultList);
    }


    @Operation(summary = "移动支付对账单")
    @GetMapping("/chs/bill")
    @PreAuthorize("@ss.hasPermission('bh:bill:query')")
    public CommonResult chsBillQuery(@Valid BillReqVO billReqVO){
        String mchType = billReqVO.getMchType();
        String mchNo = payConfig.getMchNo(mchType);
        if (StringUtils.isEmpty(mchNo)) {
            return CommonResult.error(ErrorCodeConstants.PAY_CONFIG_MCHNO_NOT_EXISTS);
        }

        billReqVO.setMchNo(mchNo);
        JSONObject resultDataMap = staticsService.chsBillQuery(billReqVO);
        List<Map<String,Object>> resultList = new LinkedList<>();
        if(!CollectionUtils.isEmpty(resultDataMap)) {
            BigDecimal p_fee = new BigDecimal(0);
            BigDecimal cash_fee = new BigDecimal(0);
            BigDecimal insurance_fee = new BigDecimal(0);
            BigDecimal acct_fee = new BigDecimal(0);
            BigDecimal fund_fee = new BigDecimal(0);
            if(!StringUtils.isEmpty(resultDataMap.get("payOrderList"))) {
                List<Map<String,Object>> list = (List<Map<String,Object>>)resultDataMap.get("payOrderList");
                List<Map<String,Object>> newList = new LinkedList<>();
                for (Map<String, Object> stringObjectMap : list) {
                    BigDecimal total_fee = (BigDecimal) stringObjectMap.get("payAmount");
                    BigDecimal total_cash_fee = (BigDecimal) stringObjectMap.get("cashAmount");
                    BigDecimal total_insurance_fee = (BigDecimal) stringObjectMap.get("insuranceAmount");
                    BigDecimal total_acct_fee = (BigDecimal) stringObjectMap.get("acctFee");
                    BigDecimal total_fund_fee = (BigDecimal) stringObjectMap.get("fundFee");
                    String trade_item = (String) stringObjectMap.get("content");
                    if(!StringUtils.isEmpty(trade_item)) {
                        try{
                            Map m = JSON.parseObject(trade_item,Map.class);
                            if(!CollectionUtils.isEmpty(m)) {
                                stringObjectMap.putAll(m);
                            }
                        }catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                    newList.add(stringObjectMap);
                    p_fee = p_fee.add(total_fee);
                    cash_fee = cash_fee.add(total_cash_fee);
                    insurance_fee = insurance_fee.add(total_insurance_fee);
                    acct_fee = acct_fee.add(total_acct_fee);
                    fund_fee = fund_fee.add(total_fund_fee);
                }

                if(!CollectionUtils.isEmpty(newList)) {
                    resultList.addAll(newList);
                }

                HashMap<String,Object> totalMap = new HashMap();
                totalMap.put("title","合计收款");
                totalMap.put("channelNo",newList.size() + "笔");
                totalMap.put("payAmount",p_fee.toString());
                totalMap.put("cashAmount",cash_fee.toString());
                totalMap.put("insuranceAmount",insurance_fee.toString());
                totalMap.put("acctFee",acct_fee.toString());
                totalMap.put("fundFee",fund_fee.toString());
                resultList.add(totalMap);
            }

            BigDecimal r_total_fee = new BigDecimal(0);
            BigDecimal r_total_cash_fee = new BigDecimal(0);
            BigDecimal r_total_insurance_fee = new BigDecimal(0);
            BigDecimal r_total_acct_fee = new BigDecimal(0);
            BigDecimal r_total_fund_fee = new BigDecimal(0);
            if(!StringUtils.isEmpty(resultDataMap.get("refundOrderList"))) {
                List<Map<String,Object>> list = (List<Map<String,Object>>)resultDataMap.get("refundOrderList");
                List<Map<String,Object>> newList = new LinkedList<>();
                for (Map<String, Object> stringObjectMap : list) {
                    BigDecimal r_fee = (BigDecimal) stringObjectMap.get("refundAmount");
                    BigDecimal r_cash_fee = (BigDecimal) stringObjectMap.get("cashAmount");
                    BigDecimal r_insurance_fee = (BigDecimal) stringObjectMap.get("insuranceAmount");
                    BigDecimal r_acct_fee = (BigDecimal) stringObjectMap.get("acctFee");
                    BigDecimal r_fund_fee = (BigDecimal) stringObjectMap.get("fundFee");
                    String trade_item = (String) stringObjectMap.get("content");
                    if(!StringUtils.isEmpty(trade_item)) {
                        try{
                            Map m = JSON.parseObject(trade_item,Map.class);
                            if(!CollectionUtils.isEmpty(m)) {
                                stringObjectMap.putAll(m);
                            }
                        }catch (Exception e) {
                            e.printStackTrace();
                        }
                    }

                    newList.add(stringObjectMap);
                    r_total_fee = r_total_fee.add(r_fee);
                    r_total_cash_fee = r_total_cash_fee.add(r_cash_fee);
                    r_total_insurance_fee = r_total_insurance_fee.add(r_insurance_fee);
                    r_total_acct_fee = r_total_acct_fee.add(r_acct_fee);
                    r_total_fund_fee = r_total_fund_fee.add(r_fund_fee);
                }

                if(!CollectionUtils.isEmpty(newList)) {
                    resultList.addAll(newList);
                }

                HashMap<String,Object> totalMap = new HashMap();
                totalMap.put("title","合计退款");
                totalMap.put("channelNo",newList.size() + "笔");
                totalMap.put("refundAmount","-" + r_total_fee.toString());
                totalMap.put("cashAmount",r_total_cash_fee.toString());
                totalMap.put("insuranceAmount",r_total_insurance_fee.toString());
                totalMap.put("acctFee",r_total_acct_fee.toString());
                totalMap.put("fundFee",r_total_fund_fee.toString());
                resultList.add(totalMap);
            }

            BigDecimal total_fee = p_fee.subtract(r_total_fee);
            HashMap<String,Object> totalMap = new HashMap();
            totalMap.put("title","总计收入");
            totalMap.put("payAmount",total_fee.toString());
            resultList.add(totalMap);
        }
        return CommonResult.success(resultList);
    }
}
